package com.freecsim.sas.kernel;

import java.io.File;
import java.util.Properties;

import org.apache.commons.configuration.XMLConfiguration;
import org.apache.log4j.PropertyConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.freecsim.sas.core.ServerContext;
import com.freecsim.sas.core.internal.InnerServiceConfigure;
import com.freecsim.sas.core.internal.InnerServiceContext;
import com.freecsim.sas.core.internal.InternalContext;
import com.freecsim.sas.core.services.IService;
import com.freecsim.sas.core.services.ServiceManagerImp;
import com.freecsim.sas.util.GplyphPrinter;

 /**
 * 
 * <p></p>
 * @version	1.0
 * @author    	老吴
 * @since 		1.6
 */
public class Kernel {

	/**
	 * 服务内核启动日志
	 */
	private static Logger logger = LoggerFactory.getLogger(Kernel.class);
	
	/**
	 * 服务名称
	 */
	private String serverName = "Kernel";
	
	private Thread shutDownThread = null;
	
	private ShutdownHandler shutdownHandler;
	
	/**
	 * 构造方法
	 */
	public Kernel(){
		String appHome = System.getProperty("app.home");
		if(appHome == null){
			appHome = ".";
			System.setProperty("app.home", appHome);
		}
		try{
			PropertyConfigurator.configure (appHome + File.separator + "conf" + File.separator +  "log4j.properties") ;
		}catch(Exception ex){
			
		}
		GplyphPrinter.printCharGraphy("SAS");
		logger.info("Starting Server...");
		try {
			ServiceManagerImp serviceManager = new ServiceManagerImp();
			XMLConfiguration config = new XMLConfiguration(new File(appHome + File.separator + "conf" + File.separator + "server.xml"));
			config.load();
			
			Document doc = config.getDocument();
			Element root = doc.getDocumentElement();
			String serverName = root.getAttribute("name");
			String shutdownPort = root.getAttribute("port");
			String shutdownCommand = root.getAttribute("shutdown");   
			
			//读取全局参数
			Properties globalProperties = new Properties();
			NodeList contextNodes = root.getElementsByTagName("context-param");
			if(contextNodes != null && contextNodes.getLength() > 0){
				globalProperties = readElementProperties((Element) contextNodes.item(0));
			}
			
			InternalContext.setGlobalParameters(globalProperties);
			NodeList servicesList = root.getElementsByTagName("services");
			if(servicesList != null && servicesList.getLength() > 0){
				Element servicesElement = (Element) servicesList.item(0);
				NodeList appsList = servicesElement.getElementsByTagName("service");
				for(int i = 0; appsList != null && i < appsList.getLength(); i++){
					Element e = (Element) appsList.item(i);
					
					NamedNodeMap attributes = e.getAttributes();
					InnerServiceContext sc = new InnerServiceContext();
					for( int k = 0; k < attributes.getLength(); k++){
						Node node = attributes.item(k);
						sc.setAttribute(node.getNodeName(), node.getNodeValue());
					}
					
					Properties serviePropts = readElementProperties(e);
					
					InnerServiceConfigure sconfig = new InnerServiceConfigure();
					sconfig.setServiceContext(sc);
					sconfig.setInitParameter(serviePropts);
					String serviceClassName = String.valueOf(sc.getAttribute("className"));
					IService s = (IService) Class.forName(serviceClassName).newInstance();
					if(s != null){
						s.init(sconfig);
					}
					serviceManager.registerService(s);
				}
			}
				
			InternalContext.setServiceManager(serviceManager);
			//加载关闭监听线程
			shutdownHandler = new ShutdownHandler(this, Integer.valueOf(shutdownPort).intValue(), shutdownCommand);
			shutDownThread = new Thread(shutdownHandler,"shutdown_thread");
			shutDownThread.start();
			logger.info(serverName + " start success.");
		} catch (Exception e) {
			logger.error(serverName + " start failed.", e);
			System.exit(0);
		}
	}
	
	/**
	 * 根据配置元素读取参数配置
	 * @param e
	 * @return
	 */
	private Properties readElementProperties(Element e){
		Properties properties = new Properties();
		if(e == null){
			return properties;
		}else{
			NodeList paramsNodes = e.getElementsByTagName("property");
			if(paramsNodes != null){
				for(int k = 0; k < paramsNodes.getLength(); k++){
					Element pe  = (Element)paramsNodes.item(k);;
					String paramName = pe.getAttribute("name");
					String paramValue = pe.getAttribute("value");
					properties.put(paramName, paramValue);
				}
			}
		}
		return properties;
	}
	
	/**
	 * 启动所有服务
	 */
	private void start(long startime){
		try {
			ServerContext.getServiceManager().startServices();
			logger.info("Server startup in " + (System.currentTimeMillis() - startime) + "ms");
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			quit();
			System.exit(0);
		}
	}
	
	
	/**
	 * 系统退出
	 */
	public void quit(){
		ServerContext.getServiceManager().closeServices();
		logger.info("Server is shutdown.");
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		long st = System.currentTimeMillis();
		Kernel kernel = new Kernel();
		kernel.start(st);
	}
}
